<?php
/**
 * 拍拍开放平台连接客户端
 *
 * PHP version 5
 *
 * @package    Project
 * @subpackage ProductCenter
 * @author     Garbin <garbinh@gmail.com>
 * @copyright  2010 Xingchangxinda Inc.
 * @version    SVN: $Id$
 */

namespace Project\Apps\Ecga\Library;

/**
 * 拍拍开放平台客户端
 *
 * @package    Project
 * @subpackage ProductCenter
 * @author     Garbin <garbinh@gmail.com>
 * @copyright  2010 Xingchangxinda Inc.
 */
class PaipaiClient
{
    public $gateway = '';
    public $uin = '';
    public $token = '';
    public $sckey = '';
    public $spid = '';

    /**
     * 设置目标环境
     *
     * 参数可选值为:test-测试环境，production-生产环境,默认为test。
     *
     * @param String $env 环境名称
     *
     * @author     Garbin <garbinh@gmail.com>
     * @return Object 实例自身
     */
    public function setEnv($env = 'test')
    {
        switch ($env)
        {
        case 'production':
                $this->gateway = 'http://api.paipai.com';
            break;

        default:
                // 默认是沙盒环境
                $this->gateway = 'http://apitest.paipai.com';
            break;
        }

        return $this;
    }

    /**
     * 生成cmdid
     *
     * 例如：http://api.paipai.com/item/addItem.xhtml，其requestURLPath="/item/addItem.xhtml "
     * 对应的cmdid="item.addItem"。
     *
     * @param string $requestURLPath 请求地址
     *
     * @author     Garbin <garbinh@gmail.com>
     * @return string
     */
	public function createCmdid($requestURLPath)
	{
		if (strlen($requestURLPath) == 0) {
            return false;
        }
		if ($requestURLPath{0} != '/') {
            return false;
        }
		if (strpos($requestURLPath, '/') === false) {
            return false;
        }
		if (strpos($requestURLPath, '.') === false) {
            return false;
        }
		$pos_start = 1;
		$pos_end = strpos($requestURLPath, '.');
		$cmd = substr($requestURLPath, $pos_start, $pos_end-1);
		$cmd = str_replace('/', '.', $cmd);

		return $cmd;
	}

    /**
     * 发送请求
     *
     * @param string $urlpath  接口地址
     * @param array  $param    请求参数
     * @param string $dataType 返回数据的数据格式，可选值"json", "xml"，默认为"json"
     *
     * @author     Garbin <garbinh@gmail.com>
     * @return  mixed 返回类型视$dataType而定
     */
    public function request($urlpath, $param, $dataType = 'json')
    {
        $initParam = array(
            'uin' => $this->uin,
            'token' => $this->token,
            'spid' => $this->spid,
            'charset' => 'utf-8',
            'format' => $dataType,
            'pureData' => 1,
        );

        $AllParam = array_merge($initParam, $param);

		$cmdid = $this->createCmdid($urlpath);
		//$sign = $this->createSign($param, $cmdid);
		$initParam['sign'] = $this->createSign($AllParam, $cmdid);
		//$strParam = $this->createStrParam($param);
		$strParam = $this->createStrParam($initParam);
		//$strParam .= 'sign='.$sign;
		$url = $this->gateway . $urlpath .'?' . $strParam;
        //$result = file_get_contents($url);
        $result = $this->curl($url, $param);
        if ($dataType == 'json') {
            $result = json_decode($result);
        } else {
            // TODO:记录日志
			$result = simplexml_load_string($result);
        }
		if ($result->errorCode != '0') {
			throw new \Exception($result->errorMessage . $url, $result->errorCode);
		}
		return $result;
    }

    /**
     * Paipai签名函数
     *
     * @param array $paramArr 请求参数数组
     * @param int   $cmdid    命令ID
     *
     * @author     Garbin <garbinh@gmail.com>
     * @return string
     */
    public function createSign($paramArr, $cmdid)
    {
        $sign = $cmdid;
        ksort($paramArr);
        foreach ($paramArr as $key => $val) {
            if ($key != '' && $val !== '') {
                $sign .= $key.$val;
            }
        }

        $sign.= $this->sckey;
        $sign = strtoupper(md5($sign));

        return $sign;
    }

    /**
     * Paipai组参函数
     *
     * @param array $paramArr 参数列表
     *
     * @author Garbin <garbinh@gmail.com>
     * @return string
     */
    public function createStrParam ($paramArr)
    {
        $strParam = '';
        foreach ($paramArr as $key => $val) {
            if ($key != '' && $val !== '') {
                $strParam .= $key.'='.urlencode($val).'&';
            }
        }

        return $strParam;
    }

    /**
     * 获取客户端实例
     *
     * @author     Garbin <garbinh@gmail.com>
     * @return Object 客户端实例
     */
    public static function getInstance()
    {
        static $obj = null;
        if ($obj === null) {
            $obj = new PaipaiClient;
        }

        return $obj;
    }
    
    /**
     * cURL方式请求
     *
     * @param string $url        请求地址
     * @param array  $postFields 请求字段
     * 
     * @return object
     */
    protected function curl($url, $postFields = null)
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_FAILONERROR, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		if (is_array($postFields) && 0 < count($postFields)) {
			$postBodyString = "";
			$postMultipart = false;
			foreach ($postFields as $k => $v) {
				//判断是不是文件上传
			    if ("@" != substr($v, 0, 1)) {
					$postBodyString .= "$k=" . urlencode($v) . "&"; 
				} else {
					//文件上传用multipart/form-data，否则用www-form-urlencoded
				    $postMultipart = true;
				}
			}
			unset($k, $v);
			curl_setopt($ch, CURLOPT_POST, true);
			if ($postMultipart) {
				curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
			} else {
				curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString, 0, -1));
			}
		}
		$reponse = curl_exec($ch);
		if (curl_errno($ch)) {
			throw new \Exception(curl_error($ch), 0);
		} else {
			$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
			if (200 !== $httpStatusCode) {
				throw new \Exception($reponse, $httpStatusCode);
			}
		}
		curl_close($ch);
		return $reponse;
	}
}
